%%%-------------------------------------------------------------------
%%% @author Rain
%%% @doc 动态编译相关
%%% @end
%%%-------------------------------------------------------------------
-module(game_util_dyn_compile).
-author("Rain").
-include("game_util_dyn_compile.hrl").

%% API
-export([compile/1]).
-export([simple_compile/2]).

%% @doc 动态编译
compile(CodeStr) ->
    {module, Module} = dynamic_compile:load_from_string(CodeStr, ?DYNAMIC_COMPILE_OPTS),
    Module.


make_module(Module) ->
    lists:flatten(io_lib:format("-module(~p).~n", [Module])).

make_export(FuncName, Arity, AccStr) ->
    lists:flatten(io_lib:format("-export([~w/~w]).~n", [FuncName, Arity])) ++ AccStr.

make_kv_func(List, FuncName, AccStr) ->
    Init = lists:flatten(io_lib:format("~w(_) -> undefined.~n", [FuncName])),
    AddStr = make_kv_func1(lists:reverse(List), FuncName, Init),
    AddStr ++ AccStr.
make_kv_func1([], _FuncName, AccStr) ->
    AccStr;
make_kv_func1([{Key, Value} | T], FuncName, AccStr) ->
    AccStr1 = lists:flatten(io_lib:format("~w(~w) -> ~w;~n", [FuncName, Key, Value])) ++ AccStr,
    make_kv_func1(T, FuncName, AccStr1).

make_record_func(List, KeyIdx, FuncName, AccStr) ->
    Init = lists:flatten(io_lib:format("~w(_) -> undefined.~n", [FuncName])),
    AddStr = make_record_func1(lists:reverse(List), KeyIdx, FuncName, Init),
    AddStr ++ AccStr.
make_record_func1([], _KeyIdx, _FuncName, AccStr) ->
    AccStr;
make_record_func1([Record | T], KeyIdx, FuncName, AccStr) when is_tuple(Record) ->
    Key = element(KeyIdx, Record),
    AccStr1 = lists:flatten(io_lib:format("~w(~w) -> ~w;~n", [FuncName, Key, Record])) ++ AccStr,
    make_record_func1(T, KeyIdx, FuncName, AccStr1).

make_list_func(L, FuncName, AccStr) ->
    lists:flatten(io_lib:format("~w() -> ~w.~n", [FuncName, L])) ++ AccStr.

simple_module(Module, SimpleArgs) ->
    ModuleName = make_module(Module),
    simple_module1(SimpleArgs, ModuleName, "", "").

simple_module1([], ModuleName, AccExport, AccBody) ->
    ModuleName ++ AccExport ++ AccBody;
simple_module1([{?SIMPLE_DYN_TYPE_KV, FuncName, List}|T], ModuleName, AccExport, AccBody) ->
    AccExport1 = make_export(FuncName, 1, AccExport),
    AccBody1 = make_kv_func(List, FuncName, AccBody),
    simple_module1(T, ModuleName, AccExport1, AccBody1);
simple_module1([{?SIMPLE_DYN_TYPE_REC, FuncName, KeyIdx, List}|T], ModuleName, AccExport, AccBody) ->
    AccExport1 = make_export(FuncName, 1, AccExport),
    AccBody1 = make_record_func(List, KeyIdx, FuncName, AccBody),
    simple_module1(T, ModuleName, AccExport1, AccBody1);
simple_module1([{?SIMPLE_DYN_TYPE_LIST, FuncName, List}|T], ModuleName, AccExport, AccBody) ->
    AccExport1 = make_export(FuncName, 0, AccExport),
    AccBody1 = make_list_func(List, FuncName, AccBody),
    simple_module1(T, ModuleName, AccExport1, AccBody1).

%% @doc 动态编译一个简单模块
simple_compile(Module, SimpleArgs) ->
    CodeStr = simple_module(Module, SimpleArgs),
    compile(CodeStr).




